// Decompiled by Jad v1.5.7g. Copyright 2000 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi 
// Source File Name:   ObjectPool.java

package com.vandagroup.common.util;

import com.vandagroup.common.exp.TimeoutException;
import java.util.Enumeration;
import java.util.Hashtable;

// Referenced classes of package com.vandagroup.common.util:
//            CleanUpThread

public abstract class ObjectPool
{

    private CleanUpThread cleaner;
    private long expirationTime;
    private long checkOutTimeout;
    private int maxObjNum;
    private int minObjNum;
    private long lastCheckOut;
    private Hashtable locked;
    public Hashtable unlocked;

    protected ObjectPool()
    {
        expirationTime = 0L;
        checkOutTimeout = 0L;
        maxObjNum = 0;
        minObjNum = 0;
        expirationTime = 30000L;
        init();
    }

    protected ObjectPool(long expireTime, long checkOutTimeout, int objMaxNum, int objMinNum)
    {
        expirationTime = 0L;
        this.checkOutTimeout = 0L;
        maxObjNum = 0;
        minObjNum = 0;
        expirationTime = expireTime;
        this.checkOutTimeout = checkOutTimeout;
        maxObjNum = objMaxNum;
        minObjNum = objMinNum;
        init();
    }

    protected synchronized void checkIn(Object obj)
    {
        if(obj != null)
        {
            locked.remove(obj);
            unlocked.put(obj, new Long(System.currentTimeMillis()));
            notifyAll();
        }
    }

    protected synchronized Object checkOut()
        throws Exception
    {
        long now = System.currentTimeMillis();
        lastCheckOut = now;
        Object obj;
        for(obj = null; obj == null;)
        {
            for(Enumeration objList = unlocked.keys(); objList.hasMoreElements();)
            {
                obj = objList.nextElement();
                if(validate(obj))
                {
                    unlocked.remove(obj);
                    locked.put(obj, new Long(now));
                    return obj;
                }
                unlocked.remove(obj);
                expire(obj);
                obj = null;
            }

            if(maxObjNum > 0)
            {
                if(unlocked.size() + locked.size() < maxObjNum)
                    obj = create();
            } else
            {
                obj = create();
            }
            if(obj == null && checkOutTimeout > 0L && System.currentTimeMillis() - now > checkOutTimeout)
                throw new TimeoutException("Get object timeout in pool");
            if(obj == null)
            {
                long timeout = checkOutTimeout > 0L ? checkOutTimeout : 5000L;
                try
                {
                    wait(timeout);
                }
                catch(InterruptedException interruptedexception) { }
            }
        }

        locked.put(obj, new Long(now));
        return obj;
    }

    synchronized void cleanUp()
    {
        Object obj = null;
        long now = System.currentTimeMillis();
        for(Enumeration e = unlocked.keys(); e.hasMoreElements();)
        {
            if(unlocked.size() + locked.size() <= minObjNum)
                break;
            obj = e.nextElement();
            if(expirationTime > 0L && now - ((Long)unlocked.get(obj)).longValue() > expirationTime)
            {
                unlocked.remove(obj);
                expire(obj);
                obj = null;
            }
        }

        System.gc();
        notifyAll();
    }

    public String monitePool()
    {
        return "Free:" + unlocked.size() + "    Locked:" + locked.size() + "   Max:" + maxObjNum;
    }

    private void init()
    {
        locked = new Hashtable();
        unlocked = new Hashtable();
        lastCheckOut = System.currentTimeMillis();
        cleaner = new CleanUpThread(this, expirationTime);
        cleaner.start();
    }

    public void release()
    {
        Object obj = null;
        for(Enumeration e = unlocked.keys(); e.hasMoreElements();)
        {
            obj = e.nextElement();
            unlocked.remove(obj);
            expire(obj);
            obj = null;
        }

        for(Enumeration e = locked.keys(); e.hasMoreElements();)
        {
            obj = e.nextElement();
            unlocked.remove(obj);
            expire(obj);
            obj = null;
        }

    }

    protected abstract Object create()
        throws Exception;

    protected abstract void expire(Object obj);

    protected abstract boolean validate(Object obj);
}
